{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "tensorflow 2,利用 keras简化\n",
    "卷积神经5层\n",
    "\n",
    "参数个数：80+876+1930=2886\n",
    "\n",
    "10轮后准确率0.977 \n",
    "\n",
    "训练时间110"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "#from tensorflow import keras"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "minst = tf.keras.datasets.mnist\n",
    "img_rows,img_cols = 28,28\n",
    "(x_train, y_train), (x_test, y_test) = minst.load_data()\n",
    "x_train = x_train.reshape(x_train.shape[0],img_rows,img_cols,1)\n",
    "x_test = x_test.reshape(x_test.shape[0],img_rows,img_cols,1)\n",
    "\n",
    "x_train = x_train.astype('float32')\n",
    "x_test = x_test.astype('float32')\n",
    "x_train = x_train / 255\n",
    "x_test = x_test / 255\n",
    "y_train_onehot = tf.keras.utils.to_categorical(y_train)\n",
    "y_test_onehot = tf.keras.utils.to_categorical(y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "#tf.__version__\n",
    "#y_train.shape\n",
    "#tf.keras.backend.image_data_format()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d (Conv2D)              (None, 26, 26, 8)         72        \n",
      "_________________________________________________________________\n",
      "max_pooling2d (MaxPooling2D) (None, 9, 9, 8)           0         \n",
      "_________________________________________________________________\n",
      "conv2d_1 (Conv2D)            (None, 7, 7, 12)          864       \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 4, 4, 12)          0         \n",
      "_________________________________________________________________\n",
      "flatten (Flatten)            (None, 192)               0         \n",
      "_________________________________________________________________\n",
      "dense (Dense)                (None, 10)                1920      \n",
      "=================================================================\n",
      "Total params: 2,856\n",
      "Trainable params: 2,856\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model = tf.keras.Sequential()\n",
    "\n",
    "model.add(tf.keras.layers.Conv2D(8, kernel_size=(3, 3),padding=\"valid\", activation='relu',use_bias=False,input_shape=(28, 28, 1)))\n",
    "model.add(tf.keras.layers.MaxPooling2D(pool_size=(3, 3),padding=\"same\"))\n",
    "model.add(tf.keras.layers.Conv2D(12, kernel_size=(3, 3),padding=\"valid\", activation='relu',use_bias=False,))\n",
    "model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2),padding=\"same\"))\n",
    "model.add(tf.keras.layers.Flatten())\n",
    "#model.add(tf.keras.layers.Dense(128, activation='relu'))\n",
    "#model.add(tf.keras.layers.Dropout(0.5))\n",
    "model.add(tf.keras.layers.Dense(10, use_bias=False,activation='softmax'))\n",
    "\n",
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 60000 samples, validate on 10000 samples\n",
      "Epoch 1/10\n",
      "60000/60000 - 13s - loss: 0.5409 - accuracy: 0.8495 - val_loss: 0.1799 - val_accuracy: 0.9480\n",
      "Epoch 2/10\n",
      "60000/60000 - 11s - loss: 0.1567 - accuracy: 0.9524 - val_loss: 0.1201 - val_accuracy: 0.9629\n",
      "Epoch 3/10\n",
      "60000/60000 - 12s - loss: 0.1214 - accuracy: 0.9628 - val_loss: 0.0937 - val_accuracy: 0.9708\n",
      "Epoch 4/10\n",
      "60000/60000 - 11s - loss: 0.1050 - accuracy: 0.9675 - val_loss: 0.0887 - val_accuracy: 0.9714\n",
      "Epoch 5/10\n",
      "60000/60000 - 11s - loss: 0.0935 - accuracy: 0.9712 - val_loss: 0.0753 - val_accuracy: 0.9751\n",
      "Epoch 6/10\n",
      "60000/60000 - 11s - loss: 0.0859 - accuracy: 0.9740 - val_loss: 0.0700 - val_accuracy: 0.9775\n",
      "Epoch 7/10\n",
      "60000/60000 - 11s - loss: 0.0799 - accuracy: 0.9754 - val_loss: 0.0720 - val_accuracy: 0.9759\n",
      "Epoch 8/10\n",
      "60000/60000 - 11s - loss: 0.0757 - accuracy: 0.9772 - val_loss: 0.0586 - val_accuracy: 0.9801\n",
      "Epoch 9/10\n",
      "60000/60000 - 11s - loss: 0.0718 - accuracy: 0.9783 - val_loss: 0.0591 - val_accuracy: 0.9798\n",
      "Epoch 10/10\n",
      "60000/60000 - 11s - loss: 0.0673 - accuracy: 0.9793 - val_loss: 0.0614 - val_accuracy: 0.9797\n",
      "Train Finished! takes: 113.38\n",
      "Test accuracy: 0.9797\n"
     ]
    }
   ],
   "source": [
    "model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\n",
    "from time import time\n",
    "startTime = time()\n",
    "history = model.fit(x_train, y_train_onehot, batch_size = 100, epochs = 10, verbose=2, validation_data = (x_test, y_test_onehot))\n",
    "\n",
    "duration = time()-startTime\n",
    "print(\"Train Finished! takes:\",\"{:.2f}\".format(duration))\n",
    "\n",
    "score = model.evaluate(x_test, y_test_onehot, verbose=0)\n",
    "#print('Test loss:', score[0])\n",
    "print('Test accuracy:', score[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#model_filename = 'models/mnist_tf2.h5'\n",
    "### 1.保存框架，权重，优化器，损失函数\n",
    "model.save('models/mnist_tf2_fw.h5')\n",
    "### 2.保存框架，不含权重和配置\n",
    "yaml_tring = model.to_yaml()\n",
    "#yaml_tring = model.to_json()\n",
    "with open('./models/mnist_tf2_f.yaml','w') as model_file:\n",
    "    model_file.write(yaml_tring)\n",
    "### 3.保存权重，不含框架和配置\n",
    "model.save_weights('models/mnist_tf2_w.h5')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 如何加载模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d (Conv2D)              (None, 26, 26, 8)         72        \n",
      "_________________________________________________________________\n",
      "max_pooling2d (MaxPooling2D) (None, 9, 9, 8)           0         \n",
      "_________________________________________________________________\n",
      "conv2d_1 (Conv2D)            (None, 7, 7, 12)          864       \n",
      "_________________________________________________________________\n",
      "max_pooling2d_1 (MaxPooling2 (None, 4, 4, 12)          0         \n",
      "_________________________________________________________________\n",
      "flatten (Flatten)            (None, 192)               0         \n",
      "_________________________________________________________________\n",
      "dense (Dense)                (None, 10)                1920      \n",
      "=================================================================\n",
      "Total params: 2,856\n",
      "Trainable params: 2,856\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\ProgramData\\Anaconda3\\lib\\site-packages\\tensorflow_core\\python\\keras\\saving\\model_config.py:76: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.\n",
      "  config = yaml.load(yaml_string)\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# 1.直接保存的可以直接加载\n",
    "model = tf.keras.Sequential()\n",
    "model = tf.keras.models.load_model('models/mnist_tf2_fw.h5')\n",
    "model.summary()\n",
    "\n",
    "# 2.先定义模型，加载框架，加载权重，最后还要定义损失函数和优化器\n",
    "model = tf.keras.Sequential() #定义模型\n",
    "with open('./models/mnist_tf2_f.yaml') as yamlfile:\n",
    "    loaded_model_yaml = yamlfile.read()\n",
    "model = tf.keras.models.model_from_yaml(loaded_model_yaml) #加载框架\n",
    "model.load_weights('./models/mnist_tf2_w.h5') #加载权重"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#1 未量化保存32bit\n",
    "converter = tf.lite.TFLiteConverter.from_keras_model(model)\n",
    "tflite_model = converter.convert()\n",
    "open(\"models/tflite_model_32.tflite\",\"wb\").write(tflite_model)\n",
    "\n",
    "# 2.float16量化\n",
    "converter = tf.lite.TFLiteConverter.from_keras_model(model)\n",
    "converter.optimizations = [tf.lite.Optimize.DEFAULT]\n",
    "converter.target_spec.supported_types = [tf.float16]\n",
    "tflite_model = converter.convert()\n",
    "open(\"models/tflite_model_16.tflite\", \"wb\").write(tflite_model)\n",
    "\n",
    "# 3.8bit量化\n",
    "def representative_data_gen():\n",
    "    data = tf.data.Dataset.from_tensor_slices(x_train).batch(1).take(100)\n",
    "    for input_value in data:\n",
    "        yield [input_value]\n",
    "\n",
    "converter = tf.lite.TFLiteConverter.from_keras_model(model)\n",
    "converter.optimizations = [tf.lite.Optimize.DEFAULT]\n",
    "converter.representative_dataset = representative_data_gen\n",
    "# Restricting supported target op specification to INT8\n",
    "converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]\n",
    "# Set the input and output tensors to uint8 \n",
    "converter.inference_input_type = tf.uint8\n",
    "converter.inference_output_type = tf.uint8\n",
    "# Convert and Save the model\n",
    "tflite_model = converter.convert()\n",
    "open(\"models/tflite_model_8.tflite\", \"wb\").write(tflite_model)\n",
    "\n",
    "# 4.动态量化\n",
    "converter = tf.lite.TFLiteConverter.from_keras_model(model)\n",
    "converter.optimizations = [tf.lite.Optimize.DEFAULT]\n",
    "tflite_model = converter.convert()\n",
    "open(\"models/tflite_model_dy.tflite\", \"wb\").write(tflite_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'python' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-6-45a3ce2a2cc7>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mpython\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__version__\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m: name 'python' is not defined"
     ]
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "tf.keras.layers.Conv2D(\n",
    "    filters, kernel_size, strides=(1, 1), padding='valid', data_format=None,\n",
    "    dilation_rate=(1, 1), activation=None, use_bias=True,\n",
    "    kernel_initializer='glorot_uniform', bias_initializer='zeros',\n",
    "    kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None,\n",
    "    kernel_constraint=None, bias_constraint=None, **kwargs\n",
    ")\n",
    "'''"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "oldHeight": 122.84966599999998,
   "position": {
    "height": "40px",
    "left": "664px",
    "right": "20px",
    "top": "77px",
    "width": "250px"
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "varInspector_section_display": "none",
   "window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
